<?php

namespace app\middleware;

use app\admin\cache\AdminCache;
use app\admin\service\AdminService;
use ReflectionClass;
use ReflectionException;
use Tinywan\ExceptionHandler\Exception\UnauthorizedHttpException;
use Tinywan\Jwt\Exception\JwtTokenException;
use Tinywan\Jwt\JwtToken;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;

class AuthCheck implements MiddlewareInterface
{
    /**
     * @throws UnauthorizedHttpException
     * @throws ReflectionException
     */
    private static array $controllerMetaCache = [];

    public function process(Request $request, callable $handler): Response
    {
        // 获取控制器元信息
        $meta = $this->getControllerMeta($request->controller);
        $noNeedLogin = $meta['noNeedLogin'];
        $noNeedAuth = $meta['noNeedAuth'];
        // 不需要登录
        if (in_array($request->action, $noNeedLogin)) {
            return $handler($request);
        }
        // 验证JWT token
        try {
            $request->admin = JwtToken::getExtend();;
        } catch (JwtTokenException $exception) {
            throw new UnauthorizedHttpException($exception->getMessage());
        }
        // 不需要鉴权
        if (in_array($request->action, $noNeedAuth)) {
            return $handler($request);
        }
        // 系统默认超级管理员，无需鉴权
        if (isset($request->admin['id']) && $request->admin['id'] === 1) {
            return $handler($request);
        }
        // 权限验证：统一权限键为 permission:method
        $permissionKey = $this->buildPermissionKey($request->path(), $request->method());
        if (!$this->checkUserPermission($request->admin['id'], $permissionKey)) {
            throw new UnauthorizedHttpException('无权限');
        }
        return $handler($request);
    }

    private function getControllerMeta(string $controllerClass): array
    {
        if (!isset(self::$controllerMetaCache[$controllerClass])) {
            $class = new \ReflectionClass($controllerClass);
            $properties = $class->getDefaultProperties();
            self::$controllerMetaCache[$controllerClass] = [
                'noNeedLogin' => $properties['noNeedLogin'] ?? [],
                'noNeedAuth' => $properties['noNeedAuth'] ?? [],
            ];
        }
        return self::$controllerMetaCache[$controllerClass];
    }

    /**
     * 构造权限键：permission:method
     * - 约定：path 使用冒号分割且小写；method 使用小写
     */
    private function buildPermissionKey(string $path, string $method): string
    {
        // 将路径转换为适合的格式 例如: admin/user/list => admin:user:list
        $path = str_replace(['/', '-'], ':', $path);
        // 移除多余的冒号
        $path = preg_replace('/:+/', ':', $path);
        // 统一为小写
        $base = strtolower($path);
        // 追加小写的请求方法
        return $base . ':' . strtolower($method);
    }

    /**
     * 检查管理员权限
     * @param int $adminId 管理员ID
     * @param string $permissionKey
     * @return bool
     */
    private function checkUserPermission(int $adminId, string $permissionKey): bool
    {
        $permissions = AdminCache::getPermissionsCache($adminId);
        if (empty($permissions)) {
            $adminService = new AdminService();
            $admin = $adminService->getInfo($adminId);
            // 刷新管理员所有缓存
            AdminCache::refreshAllCache($admin);
            $permissions = AdminCache::getPermissionsCache($adminId);
        }
        return in_array($permissionKey, $permissions);
    }
}
